#include <u_syscall.h>
#include <stdarg.h>

#define BUFF_LEN    1024
static U08          print_buff[BUFF_LEN] = {0};
// 用于数值 0 ~ 15 转成对应的字符 '0' ~ 'F'
static const U08 IntToStr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

/******************************************************************************
* 函数名称: void TaskDestory(void)
* 功能说明: 销毁当前任务
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
E_RET TaskDestory(void)
{
    return _SYS_CALL0(_NR_TaskDestory);
}


/******************************************************************************
* 函数名称: U32 print(const char * fmt, ...)
* 功能说明: 用户打印
* 输入参数: const char * fmt    --输出格式, 目前支持的格式: 
                                        %c: 字符
                                        %s: 字符串 
                                        %x: 十六进制 
                                        %d: 十进制
    　　　　...                 --可变参数  
* 输出参数: 无
* 函数返回: 成功打印的字符个数
* 其它说明: 无
******************************************************************************/
U32 print(const char * fmt, ...)
{
    va_list args;
    U32     index = 0;
    U08*    ptr = print_buff;
    U08*    pTmp = NULL;
    S16     i = 0;
    U08     tmp = 0;
    U32     num_x = 0;
    S32     num_d = 0;
    U08     isFirst0 = 0;
    U08     decnum[18];
    U08     decno  = 0;
    
    va_start(args, fmt);

    // 遍历字符串 fmt
    for(; *fmt; ++fmt)
    {
        // 寻找格式转换字符 '%', 如果不是 '%', 则将其转存到 print_buff 中
        if(*fmt != '%')
        {
            if(index < BUFF_LEN)
                ptr[index++] = *fmt;
            continue;
        }

        // 如果找到了 '%', 则取 '%' 后的第一个字符
        ++fmt;             
        switch (*fmt)           // 根据 '%' 后的字符类型采取不同的打印接口
        {
            case 'c':           // 字符
                if(index < BUFF_LEN)
                    ptr[index++] = (U08)va_arg(args, U32);
                break;

            case 's':           // 字符串
                pTmp = (U08 *)va_arg(args, U32);
                while(*pTmp)
                {
                    if(index < BUFF_LEN)
                        ptr[index++] = *pTmp++;
                }
                break;

            case 'x':           // 十六进制     
                ptr[index++] = '0';
                ptr[index++] = 'x';
                num_x = (U32)va_arg(args, U32);
                for(i = 0; i < 8; i++)
                {
                    tmp = num_x & 0xF;
                    num_x = num_x >> 4;
                    if(index < BUFF_LEN)
                        ptr[index+7-i] = IntToStr[tmp];
                }
                index += 9;
                break;
            
            case 'd':           // 十进制   
                num_d = (S32)va_arg(args, U32);
                if(num_d < 0)
                {
                    if(index < BUFF_LEN)
                        ptr[index++] = '-';
                    num_d = -num_d;
                }
                while (1)
                {
                    decnum[decno] = num_d % 10;
                    num_d = num_d / 10;
                    if (num_d == 0) 
                       break;
                    decno++;
                }
                for (i = decno+1; i > 0; i--)
                {
                    if(index < BUFF_LEN)
                        ptr[index++] = IntToStr[decnum[i-1]];
                }
                break;
            
            default:
                break;
        }
    }

    va_end(args);

    return _SYS_CALL2(_NR_print, ptr, index);
}

/******************************************************************************
* 函数名称: E_RET SetCursorPos(U16 x, U16 y)
* 功能说明: 设置光标位置
* 输入参数: U16 x		--横坐标
    　　　　U16 y       --纵坐标
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SetCursorPos(U16 x, U16 y)
{
    return _SYS_CALL2(_NR_SetCursorPos, x, y);
}

